<template>
    <div class="g6-wrap">
        <h3 class="title">
            <i class="circle-icon"></i>
            <span>引擎状态监控</span>
            <el-steps>
                <el-step :status="stepStatus['start']" :icon="stepIconStatus[stepStatus['start']]" title="初始化"></el-step>
                <el-step :status="stepStatus['outside']" :icon="stepIconStatus[stepStatus['outside']]" title="外部数据加载"></el-step>
                <el-step :status="stepStatus['inside']" :icon="stepIconStatus[stepStatus['inside']]" title="内部数据加载"></el-step>
                <el-step :status="stepStatus['dataConversion']" :icon="stepIconStatus[stepStatus['dataConversion']]" title="数据转换加载"></el-step>
                <el-step :status="stepStatus['entry']" :icon="stepIconStatus[stepStatus['entry']]" title="条目初始化"></el-step>
                <el-step :status="stepStatus['engine']" :icon="stepIconStatus[stepStatus['engine']]" title="引擎运行中"></el-step>
            </el-steps>
            <div class="title-right">
                <!-- <el-tooltip content="详情" placement="bottom" effect="light" popper-class="monitor-tooltip">
                    <i class="el-icon-tickets"></i>
                </el-tooltip> -->
                <el-tooltip content="刷新" placement="bottom" effect="light" popper-class="monitor-tooltip">
                    <i class="el-icon-refresh-right" @click="handleRefresh"></i>
                </el-tooltip>
            </div>
        </h3>
        <div class="g6-box">
            <div class="engine-diagram" key="engine-diagram">
                <div class="engine-diagram-icon">
                    <dl v-for="icon in engineIcon" :key="icon.text">
                        <dt><img :src="icon.img" /></dt>
                        <dd>
                            <span>{{ icon.text }}</span>
                        </dd>
                    </dl>
                </div>
                <div class="engine-diagram-box" ref="box"></div>
                <div class="engine-diagram-time">
                    <dl style="padding-left: 70px">
                        <dt>
                            <span class="text-align">开始时间：</span>
                            <b>{{ startTime || '--' }}</b>
                        </dt>
                        <dd>
                            <span class="text-align">结束时间：</span>
                            <b>{{ endTime || '--' }}</b>
                        </dd>
                        <dd>
                            <span class="text-align">耗时：</span>
                            <b>{{ elapsedTime > -1 ? dealTime(elapsedTime) : '--' }}</b>
                        </dd>
                    </dl>
                </div>
            </div>
        </div>
        <el-row v-show="currentG6Node === '引擎运行中'" class="table-box">
            <el-col :span="4" class="flex-center">
                <span class="pos-title">当前引擎运行状态：</span>

                <div class="two-big-btn">
                    <div class="btn-1" :class="engineStatus ? 'active' : ''"><span>正常</span></div>
                    <div class="btn-2" :class="!engineStatus ? 'active' : ''"><span>异常</span></div>
                </div>

                <!-- <div class="traffic-light"></div> -->
            </el-col>
            <el-col :span="4" class="flex-center circle-text">
                <dl>
                    <dt>
                        <span class="text-align">开始时间：</span>
                        <b>{{ endTime || '--' }}</b>
                    </dt>
                    <dd>
                        <span class="text-align">正常运行时间：</span>
                        <b>{{ engineStatus ? getTimehms : '--' }}</b>
                    </dd>
                    <dd>
                        <span class="text-align">状态：</span>
                        <b v-show="calculateEngineStateType === 'INITIALIZED'" class="blue">运行正常</b>
                        <b v-show="calculateEngineStateType !== 'INITIALIZED'" class="red">运行异常</b>
                    </dd>
                </dl>
            </el-col>
            <el-col :span="16">
                <h3 class="title">
                    <!-- <i class="circle-icon"></i> -->
                    <span class="table-title">当日引擎运行状态更新记录:</span>
                    <div class="title-right">
                        <el-button type="primary" size="mini" @click="handleExport">导出</el-button>
                        <el-tooltip content="详情" placement="bottom" effect="light" popper-class="monitor-tooltip">
                            <i class="el-icon-full-screen" @click="engineVisible = true"></i>
                        </el-tooltip>
                    </div>
                </h3>
                <div class="table">
                    <vxe-table
                        :key="tableKey"
                        :data="tableDetailData2"
                        ref="vxeTable2"
                        keep-source
                        :column-config="{ isHover: true }"
                        :row-config="{ isHover: true }"
                        :filter-config="{ remote: true }"
                        :sort-config="{ defaultSort: { field: sortProp2, order: sortOrder2 }, orders: ['desc', 'asc', null], remote: true }"
                        border
                        style="width: 100%"
                        height="100%"
                        auto-resize
                        @filter-change="handleFilter2"
                        @sort-change="handleSort2"
                        header-align="center"
                        stripe
                        resizable
                        :resizable-config="{ minWidth: '80' }"
                        show-header-overflow
                    >
                        <vxe-column
                            field="oldStatus"
                            title="原状态"
                            :filters="[
                                { label: '连接正常', value: '0' },
                                { label: '连接异常', value: '1' },
                            ]"
                            align="center"
                            show-overflow
                            sortable
                        >
                            <template slot-scope="scope">
                                <span :style="getStyle('oldStatus', scope.row['oldStatus'])">
                                    {{ statusEnum[scope.row['oldStatus']] }}
                                </span>
                            </template>
                        </vxe-column>
                        <vxe-column
                            field="newStatus"
                            title="新状态"
                            :filters="[
                                { label: '连接正常', value: '0' },
                                { label: '连接异常', value: '1' },
                            ]"
                            align="center"
                            show-overflow
                            sortable
                        >
                            <template slot-scope="scope">
                                <span :style="getStyle('newStatus', scope.row['newStatus'])">
                                    {{ statusEnum[scope.row['newStatus']] }}
                                </span>
                            </template>
                        </vxe-column>

                        <vxe-column field="updateTime" title="更新时间" align="center" show-overflow sortable>
                            <template slot-scope="scope">
                                <span>
                                    {{ handleDateAndTime(scope.row) }}
                                </span>
                            </template>
                        </vxe-column>
                    </vxe-table>
                </div>
            </el-col>
        </el-row>
        <el-row v-show="currentG6Node !== '引擎运行中'" class="table-box">
            <el-col :span="4" class="flex-center">
                <el-progress type="circle" :percentage="currentDetailMsg.percentComplete" color="#87d068"> </el-progress>
                <div class="circle-title">{{ currentG6Node }}</div>
            </el-col>
            <el-col :span="4" class="flex-center circle-text">
                <dl>
                    <dt>
                        <span class="text-align">开始时间：</span>
                        <b>{{ currentDetailMsg.startTime || '--' }}</b>
                    </dt>
                    <dd>
                        <span class="text-align">结束时间：</span>
                        <b>{{ currentDetailMsg.endTime || '--' }}</b>
                    </dd>
                    <dd>
                        <span class="text-align">耗时：</span>
                        <b>{{ currentDetailMsg.elapsedTime > -1 ? dealTime(currentDetailMsg.elapsedTime) : '--' }}</b>
                    </dd>
                    <dd>
                        <span class="text-align">状态：</span>
                        <b>{{ resultTypeEnum[currentDetailMsg.resultType] }}</b>
                    </dd>
                </dl>
            </el-col>
            <el-col :span="16">
                <h3 class="title">
                    <span class="table-title"
                        >{{ currentG6Node }}结果:
                        <b :class="getResultTypeColor(currentDetailMsg.resultType)">{{ resultTypeEnum[currentDetailMsg.resultType] }}</b></span
                    >
                    <span class="table-title"
                        >{{ currentG6Node }}总量: <b class="blue">{{ currentDetailMsg.totalLoadSizeGB }}</b></span
                    >
                    <span class="table-title"
                        >{{ currentG6Node }}总条数: <b class="blue">{{ currentDetailMsg.totalLoadAmount }}</b> 条</span
                    >

                    <div class="title-right">
                        <el-button type="primary" size="mini" @click="handleExport">导出</el-button>
                        <el-tooltip content="详情" placement="bottom" effect="light" popper-class="monitor-tooltip">
                            <i class="el-icon-full-screen" @click="engineVisible = true"></i>
                        </el-tooltip>
                    </div>
                </h3>
                <div class="table">
                    <vxe-table
                        :key="tableKey"
                        :data="tableDetailData"
                        ref="vxeTable"
                        keep-source
                        :column-config="{ isHover: true }"
                        :row-config="{ isHover: true }"
                        :filter-config="{ remote: true }"
                        :sort-config="{ defaultSort: { field: sortProp, order: sortOrder }, orders: ['desc', 'asc', null], remote: true }"
                        border
                        style="width: 100%"
                        height="100%"
                        auto-resize
                        @filter-change="handleFilter"
                        @sort-change="handleSort"
                        header-align="center"
                        stripe
                        resizable
                        :resizable-config="{ minWidth: '80' }"
                        show-header-overflow
                    >
                        <vxe-column
                            field="tableName"
                            title="表名"
                            sortable
                            width="150"
                            :filters="[{ data: '' }]"
                            :filter-render="{ name: 'FilterInput' }"
                            show-overflow
                        >
                            <template #filter="{ $panel, column }">
                                <el-input
                                    class="my-input"
                                    type="type"
                                    v-for="(option, index) in column.filters"
                                    :key="index"
                                    v-model="option.data"
                                    @input="$panel.changeOption($event, !!option.data, option)"
                                />
                            </template>
                        </vxe-column>

                        <vxe-column field="loadSizeMB" title="数据量加载(MB)" sortable show-overflow width="150"> </vxe-column>

                        <vxe-column field="loadAmount" title="数据加载条数" sortable width="140" show-overflow> </vxe-column>

                        <vxe-column field="finishTimes" title="加载时长(ms)" sortable width="140" show-overflow> </vxe-column>

                        <vxe-column
                            field="resultType"
                            title="结果"
                            :filters="[
                                { label: '失败', value: '1' },
                                { label: '成功', value: '0' },
                            ]"
                            show-overflow
                            width="90"
                            sortable
                        >
                            <template slot-scope="scope">
                                <span :style="getStyle('resultType', scope.row['resultType'])">
                                    {{ resultTypeEnum[scope.row['resultType']] || '--' }}
                                </span>
                            </template>
                        </vxe-column>
                        <vxe-column
                            field="logInfo"
                            title="日志信息"
                            :filters="[{ data: '' }]"
                            :filter-render="{ name: 'FilterInput' }"
                            show-overflow
                            sortable
                        >
                            <template #filter="{ $panel, column }">
                                <el-input
                                    class="my-input"
                                    type="type"
                                    v-for="(option, index) in column.filters"
                                    :key="index"
                                    v-model="option.data"
                                    @input="$panel.changeOption($event, !!option.data, option)"
                                />
                            </template>
                        </vxe-column>
                        <vxe-column field="loadDateTime" title="加载时间" show-overflow width="120" sortable> </vxe-column>
                    </vxe-table>
                </div>
            </el-col>
        </el-row>

        <!-- 引擎运行状态历史记录 -->
        <EngineHistory
            v-if="engineVisible"
            :currentG6Node="currentG6Node"
            :engineVisible="engineVisible"
            :allCodeEnum="allCodeEnum"
            :currentDetailMsg="currentDetailMsg"
            @close="engineVisible = false"
        ></EngineHistory>

        <yh-dialog drag title="请选择导出节点" :visible.sync="exportVisible" width="600px" :close-on-click-modal="false">
            <div style="text-align: center">
                <span style="margin-left: -5%">节点: </span>
                <el-select v-model="exportG6Node" filterable allow-create placeholder="请选择" size="mini">
                    <el-option key="all" label="当日引擎运行状态更新记录" value="当日引擎运行状态更新记录"></el-option>
                    <el-option key="HS" label="O32数据加载" value="HS"></el-option>
                    <el-option key="CH" label="财汇数据加载" value="CH"></el-option>
                    <el-option key="GZ" label="估值数据加载" value="GZ"></el-option>
                    <el-option v-for="i in exportStorage" :key="i.typeCode" :label="i.typeDes" :value="i.typeCode"></el-option>
                </el-select>
            </div>
            <div slot="footer" class="dialog-footer">
                <el-button size="mini" type="danger" @click="exportList" :loading="exportLoading">导出选中节点</el-button>
                <el-button size="mini" type="primary" @click="exportList('当日引擎运行状态更新记录')" :loading="exportLoading"
                    >导出全部节点</el-button
                >
            </div>
        </yh-dialog>
    </div>
</template>

<script lang="ts">
import { Vue, Component, Watch } from 'vue-property-decorator';
import G6 from '@antv/g6';
import XEUtils from 'xe-utils';
import EngineHistory from './engine-history.vue';
import { engineState } from '@/pages/system-maintence/api';
import { dateFormat, timeFormat, PrefixInteger } from '@/utils/tools';
import { downLoadFile } from '@/utils/request';

let Util = G6.Util;
// 图片动画
G6.registerNode(
    'inner-animate',
    {
        afterDraw(cfg, group) {
            const size = cfg.size;
            const width = size[0] - 3;
            const height = size[1] - 3;
            const image = group.addShape('image', {
                attrs: {
                    x: -width / 2,
                    y: -height / 2,
                    width,
                    height,
                    img: cfg.img,
                    // cursor: 'pointer',
                },
                name: 'image-shape',
            });
            image.animate(
                ratio => {
                    const matrix = Util.mat3.create();
                    const toMatrix = Util.transform(matrix, [['r', ratio * Math.PI * 2]]);
                    return {
                        matrix: toMatrix,
                    };
                },
                {
                    repeat: true,
                    duration: 3000,
                    easing: 'easeLinear',
                }
            );
        },
    },
    'circle'
);

G6.registerEdge(
    'line-dash-straight',
    {
        afterDraw(cfg, group) {
            // get the first shape in the group, it is the edge's path here=
            const shape = group.get('children')[0];
            let index = 0;
            // Define the animation
            shape.animate(
                () => {
                    index++;
                    if (index > 9) {
                        index = 0;
                    }
                    const res = {
                        lineDash: [4, 4, 4, 4],
                        lineDashOffset: -index,
                    };
                    // returns the modified configurations here, lineDash and lineDashOffset here
                    return res;
                },
                {
                    repeat: true, // whether executes the animation repeatly
                    duration: 3000, // the duration for executing once
                }
            );
        },
    },
    'circle'
);
// 正常未初始化时的图标
const INFO_NODE = {
    style: {
        fill: 'rgb(222,222,222)',
        stroke: 'gray',
        // cursor: 'pointer',
    },
    state: 'wait',
};
const INFO_NODE_IMG =
    '';

// 正在初始化时的图标
const SYNC_NODE = {
    size: [18, 18],
    type: 'inner-animate',
    img: '',
    style: {
        fill: 'rgb(255,255,255)',
        stroke: 'rgb(255,255,255)',
    },
    state: 'loading',
};

// 初始化成功的图标
const SUCCESS_NODE = {
    style: {
        // cursor: 'pointer',
    },
    state: 'finish',
};
const SUCCESS_NODE_IMG =
    '';

// 初始化失败的图标
const ERROR_NODE = {
    size: [25, 25],
    type: 'image',
    img: '',
    style: {
        fill: 'rgb(255,255,255)',
        stroke: 'rgb(255,255,255)',
        // cursor: 'pointer',
    },
    state: 'error',
};

// 跳过时的图标
const SKIP_NODE = {
    size: [18, 18],
    type: 'image',
    img: '',
    style: {
        fill: 'rgb(255,255,255)',
        stroke: 'rgb(255,255,255)',
        // cursor: 'pointer',
    },
    state: 'finish',
};

const INFO_EDGE = {
    style: {
        stroke: 'rgb(150,150,150)',
    },
    state: 'wait',
};

const SYNC_EDGE = {
    style: {
        stroke: '#1890ff',
    },
    type: 'line-dash-straight',
    state: 'finish',
};
const SUCCESS_EDGE = {
    style: {
        stroke: '#1890ff',
    },
    state: 'finish',
};
const ERROR_EDGE = {
    style: {
        stroke: 'red',
    },
    state: 'error',
};

const resultType: any = {
    '0': '成功',
    '1': '失败',
    '2': '运行中',
};

const tooltip = new G6.Tooltip({
    offsetX: 10,
    offsetY: 10,
    // the types of items that allow the tooltip show up
    // 允许出现 tooltip 的 item 类型
    itemTypes: ['node'],
    // custom the tooltip's content
    // 自定义 tooltip 内容
    getContent: e => {
        const outDiv = document.createElement('div');

        if (!e.item.getModel().label) {
            return null;
            // outDiv.style.display = 'none';
            // return outDiv;
        }
        if (!e.item.getModel().initialize) {
            return null;
            // outDiv.style.display = 'none';
            // return outDiv;
        }

        outDiv.style.width = 'fit-content';
        // outDiv.style.padding = '0px 0px 20px 0px';
        outDiv.innerHTML = `
         <h4> ${e.item.getModel().label}</h4>
         <ul>
           <li>开始时间:${e.item.getModel().initialize.startTime} </li>
         </ul>
         <ul>
           <li>结束时间: ${e.item.getModel().initialize.endTime || '--'}</li>
         </ul>
         <ul>
           <li>耗时: ${e.item.getModel().initialize.elapsedTime > -1 ? e.item.getModel().initialize.elapsedTime : '--'}秒</li>
         </ul>
         <ul>
           <li>状态:  ${resultType[e.item.getModel().initialize.resultType] || '--'}</li>
         </ul>
        `;

        return outDiv;
    },
});

export interface pages {
    total?: number;
    pageSize?: number;
    currentPage?: number;
}

@Component({
    name: 'ServeExecutionMonitor',
    components: { EngineHistory },
})
export default class ServeExecutionMonitor extends Vue {
    private renderG6: any = null;

    private startTime: string = '';
    private endTime: string = '';
    private elapsedTime: number = 0;

    // 示例图标
    private engineIcon = [
        {
            img: INFO_NODE_IMG,
            text: '未开始',
        },
        {
            img: SKIP_NODE.img,
            text: '跳过',
        },
        {
            img: SYNC_NODE.img,
            text: '进行中',
        },
        {
            img: ERROR_NODE.img,
            text: '错误',
        },
        {
            img: SUCCESS_NODE_IMG,
            text: '完成',
        },
    ];

    private currentG6Node: any = '';
    private currentDetailMsg: any = {
        startTime: '',
        endTime: '',
        elapsedTime: '',
        resultType: '',
        totalLoadSizeGB: '',
        totalLoadAmount: '',
    };

    private tableDetailData: any[] = [];
    private tableDetailData2: any[] = [];
    private tableKey: number = 1;

    private ThresholdTypeArr: any[] = [];

    private iconDom: any = null; // 图标dom

    private stepStatus: any = {
        start: 'wait',
        outside: 'wait',
        inside: 'wait',
        dataConversion: 'wait',
        entry: 'wait',
        engine: 'finallyWait',
    };

    private stepIconStatus: any = {
        finish: 'el-icon-circle-check',
        wait: 'el-icon-circle-check',
        loading: 'el-icon-loading',
        error: 'el-icon-circle-close',
        finallySuccess: 'el-icon-video-play',
        finallyWait: 'el-icon-video-play',
    };

    private elapsedTimer: any = null; // 耗时定时器
    private elapsedTimer2: any = null; // 耗时定时器
    private elapsedTimer3: any = null; // 运行时间定时器

    private resultTypeEnum: any = {
        '0': '成功',
        '1': '失败',
        '2': '运行中',
    };

    private changeIconCols: any[] = [2, 4]; // 第一三列修改筛选图标  漏斗改放大镜

    // 实际排序参数字段
    sortEnum: any = {
        tableName: 'C_TABLE_NAME',
        loadAmount: 'N_LOAD_AMOUNT',
        finishTimes: 'N_FINISH_TIMES',
        resultType: 'C_RESULT_TYPE',
        logInfo: 'C_LOG_INFO',
        loadDateTime: 'D_LOAD_DATE_TIME',
        loadSizeMB: 'N_LOAD_SIZE',
    };

    sortEnum2: any = {
        oldStatus: 'C_OLD_STATUS',
        newStatus: 'C_NEW_STATUS',
        // '': 'D_UPDATE_DATE',
        updateTime: 'D_UPDATE_TIME',
    };
    private sortProp: string = 'loadDateTime'; // 默认排序字段
    private sortOrder: string = 'desc'; // 默认排序方式
    private sortParam: string = 'D_LOAD_TIME desc';

    private sortProp2: string = 'updateTime'; // 默认排序字段
    private sortOrder2: string = 'desc'; // 默认排序方式
    private sortParam2: string = 'D_UPDATE_TIME desc';

    private searchParams: any = {
        tableName: '',
        resultTypes: [],
        logInfo: '',
    };

    private searchParams2: any = {
        oldStatuses: [],
        newStatuses: [],
    };

    private paging: pages = {
        total: 0,
        pageSize: 1000,
        currentPage: 1,
    };

    private statusEnum: any = {
        '0': '连接正常',
        '1': '连接异常',
    };

    private engineStatus: boolean = true; // 引擎运行状态

    private engineVisible: boolean = false;

    private jumpOverETL: boolean = false; // 引擎是否跳过ETL
    private calculateEngineStateType: string = ''; // 引擎当前状态

    // 初始化数据
    private initializeData: any = {
        calculateEngineStateType: 'INIT_DATA',
        instructionInitDataState: {
            afterEtlInitErrors: [], // 第三列报错的
            afterEtlInitFinishs: [], // 第三列已完成的
            afterEtlInits: ['转换指令穿透', '动态维度增量同步', '指令数据加载', '原始范围加载', '条目增量同步'], // 第三列的所有
            beforeEtlInitErrors: [], // 第一列报错的
            beforeEtlInitFinishs: [], // 第一列已完成的
            beforeEtlInits: ['外部条目加载', '外部数据加载', '初始化指令号与序列号,清除恒生指令', '穿透数据清理', '动态维度加载'], // 第一列的所有
            instrctionInitDataStateType: 'TOGETHER_ETL', // ETL的状态
            jumpOverETL: false, // ETL之前是否为跳过状态 第一列是否是跳过
            messageCode: '71de-c501-2a47-1667368804651',
            togetherEtlInitErrors: [],
            togetherEtlInitFinishs: [], // 已完成的
            togetherEtlInits: ['监控屏同申报缓存加载', '监控屏初始化配置', '内存数据加载', '基础数据加载', '转换持仓穿透'], // 第二列的所有
        },
        engineStatus: 'UNINITIALIZED',
        messageCode: '71de-c501-2a47-1667368804651',
    };
    // 初始化数据 跳过ETL
    private initializeDataJumpEtl: any = {
        calculateEngineStateType: 'INIT_DATA',
        instructionInitDataState: {
            afterEtlInitErrors: [], // 第三列报错的
            afterEtlInitFinishs: [], // 第三列已完成的
            afterEtlInits: ['转换指令穿透', '指令数据加载', '原始范围加载'], // 第三列的所有
            beforeEtlInitErrors: [], // 第一列报错的
            beforeEtlInitFinishs: [], // 第一列已完成的
            beforeEtlInits: ['初始化指令号与序列号,清除恒生指令', '穿透数据清理', '动态维度加载'], // 第一列的所有
            instrctionInitDataStateType: 'TOGETHER_ETL', // ETL的状态
            jumpOverETL: true, // ETL之前是否为跳过状态 第一列是否是跳过
            messageCode: '71de-c501-2a47-1667368804651',
            togetherEtlInitErrors: [],
            togetherEtlInitFinishs: [], // 已完成的
            togetherEtlInits: ['内存数据加载', '基础数据加载', '转换持仓穿透'], // 第二列的所有
        },
        messageCode: '71de-c501-2a47-1667368804651',
    };
    private uninitializeData: any = {
        calculateEngineStateType: 'UNINITIALIZED',
        instructionInitDataState: {
            afterEtlInitErrors: [], // 第三列报错的
            afterEtlInitFinishs: [], // 第三列已完成的
            afterEtlInits: ['转换指令穿透', '动态维度增量同步', '指令数据加载', '原始范围加载', '条目增量同步'], // 第三列的所有
            beforeEtlInitErrors: [], // 第一列报错的
            beforeEtlInitFinishs: [], // 第一列已完成的
            beforeEtlInits: ['外部条目加载', '外部数据加载', '初始化指令号与序列号,清除恒生指令', '穿透数据清理', '动态维度加载'], // 第一列的所有
            instrctionInitDataStateType: 'TOGETHER_ETL', // ETL的状态
            jumpOverETL: false, // ETL之前是否为跳过状态 第一列是否是跳过
            messageCode: '71de-c501-2a47-1667368804651',
            togetherEtlInitErrors: [],
            togetherEtlInitFinishs: [], // 已完成的
            togetherEtlInits: ['监控屏同申报缓存加载', '监控屏初始化配置', '内存数据加载', '基础数据加载', '转换持仓穿透'], // 第二列的所有
        },
        engineStatus: 'UNINITIALIZED',
        messageCode: '71de-c501-2a47-1667368804651',
    };

    private allCodeEnum: any[] = [];
    private allNodeTips: any = {};

    private loading: boolean = false;

    private exportVisible: boolean = false;
    private exportG6Node: string = '';

    private exportLoading: boolean = false;

    private exportStorage: any[] = [];

    private pollingTimer: any = null;

    private durationTime: any = null; // 正常运行时间

    async mounted() {
        await this.getAllCodeEnum();
        await this.getAllNodeResult();
        await this.getEngineData();
        this.renderG6 = new G6.Graph({
            container: this.$refs.box as HTMLElement,
            width: 1370,
            height: 270,
            plugins: [tooltip], // 配置 Tooltip 插件
        });

        // 单击节点
        this.renderG6.on('node:click', e => {
            console.log('单击', e.item._cfg);
            if (!e.item._cfg.model.label || e.item._cfg.model.label === '开始') {
                return;
            }
            this.currentG6Node = e.item._cfg.model.label;
            this.getEngineDetailData();
            this.getEngineDetailTable();
        });

        this.changeTable();

        this.pollingTimer = setInterval(() => {
            this.getAllNodeResult('autoRefresh');
            this.getEngineData('autoRefresh');
            this.getEngineDetailData('autoRefresh');
            this.getEngineDetailTable('autoRefresh');
        }, 60000);
    }

    beforeDestroy() {
        if (this.elapsedTimer) {
            clearInterval(this.elapsedTimer);
            this.elapsedTimer = null;
        }
        if (this.elapsedTimer2) {
            clearInterval(this.elapsedTimer2);
            this.elapsedTimer2 = null;
        }
        if (this.elapsedTimer3) {
            clearInterval(this.elapsedTimer3);
            this.elapsedTimer3 = null;
        }
        if (this.pollingTimer) {
            clearInterval(this.pollingTimer);
            this.pollingTimer = null;
        }
    }

    handleDateAndTime(values) {
        let retValue = '--';
        if (values) {
            let date = String(values.updateDate);
            let time = String(values.updateTime);
            retValue = dateFormat(date) + '  ' + timeFormat(time);
        }
        return retValue;
    }

    // 获取引擎状态
    private async getEngineData(operateType?: string) {
        if (this.loading) {
            return;
        }
        this.loading = true;
        engineState(operateType).then((res: any) => {
            this.loading = false;

            //  特殊处理 开始时
            if (!res.process && res.request.jumpOverETL) {
                res.process = JSON.stringify(this.initializeData);
            }
            if (!res.process && !res.request.jumpOverETL) {
                res.process = JSON.stringify(this.initializeDataJumpEtl);
            }
            if (res.state === 'UNINITIALIZED') {
                // 因为接口process有缓存 所以当引擎未开始时 不使用接口的数据 使用预设的数据
                res.process = JSON.stringify(this.uninitializeData);
            }

            console.log('引擎状态msg', JSON.parse(res?.process || '{}'));
            let state = res.state;
            let result = JSON.parse(res?.process || '{}');
            // if (state !== result.calculateEngineStateType) {
            //     result.calculateEngineStateType = result;
            // }

            // debugger;
            // 讲外部数据加载拆分成3块
            const index = result.instructionInitDataState.beforeEtlInits.indexOf('外部数据加载');
            const arr = ['财汇数据加载', 'O32数据加载', '估值数据加载'];
            if (index !== -1) {
                result.instructionInitDataState.beforeEtlInits.splice(index, 1);
                result.instructionInitDataState.beforeEtlInits = [...arr, ...result.instructionInitDataState.beforeEtlInits];
            }
            const index2 = result.instructionInitDataState.beforeEtlInitFinishs.indexOf('外部数据加载');
            if (index2 !== -1) {
                result.instructionInitDataState.beforeEtlInitFinishs.splice(index2, 1);
                result.instructionInitDataState.beforeEtlInitFinishs = [...arr, ...result.instructionInitDataState.beforeEtlInitFinishs];
            }
            const index3 = result.instructionInitDataState.beforeEtlInitErrors.indexOf('外部数据加载');
            if (index3 !== -1) {
                result.instructionInitDataState.beforeEtlInitErrors.splice(index3, 1);
                result.instructionInitDataState.beforeEtlInitErrors = [...arr, ...result.instructionInitDataState.beforeEtlInitErrors];
            }

            // 处理信息 渲染G6
            this.handleMessage(result);

            this.startTime = result.startInitTime?.slice(11, 19);
            this.endTime = result.stopInitTime?.slice(11, 19);
            // 获取耗时
            this.elapsedTime = this.calcCostTime(result.startInitTime, result.stopInitTime, this.elapsedTimer, '1');

            this.jumpOverETL = res.request.jumpOverETL;
            // this.calculateEngineStateType = result.calculateEngineStateType;
            this.calculateEngineStateType = res.state; // 用外面的state, json里面的state有缓存

            if (result.engineStatus && result.engineStatus === 'UNINITIALIZED') {
                this.calculateEngineStateType = null;
                this.engineStatus = false;
            }

            if (this.calculateEngineStateType !== 'INITIALIZED') {
                this.engineStatus = false;
            } else {
                this.engineStatus = true;
            }

            // 获取引擎节点
            if (!this.currentG6Node) {
                if (res.state === 'INITIALIZED') {
                    this.currentG6Node = '引擎运行中';
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (res.state === 'INIT_ENTRY') {
                    this.currentG6Node = '条目初始化';
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (res.state === 'UNINITIALIZED') {
                    this.currentG6Node = '引擎运行中';
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (result.instructionInitDataState.afterEtlInitErrors && result.instructionInitDataState.afterEtlInitErrors.length) {
                    this.currentG6Node = result.instructionInitDataState.afterEtlInitErrors[0];
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (result.instructionInitDataState.afterEtlInitFinishs && result.instructionInitDataState.afterEtlInitFinishs.length) {
                    this.currentG6Node = result.instructionInitDataState.afterEtlInitFinishs[0];
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (result.instructionInitDataState.togetherEtlInitErrors && result.instructionInitDataState.togetherEtlInitErrors.length) {
                    this.currentG6Node = result.instructionInitDataState.togetherEtlInitErrors[0];
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (result.instructionInitDataState.togetherEtlInitFinishs && result.instructionInitDataState.togetherEtlInitFinishs.length) {
                    this.currentG6Node = result.instructionInitDataState.togetherEtlInitFinishs[0];
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (result.instructionInitDataState.beforeEtlInitErrors && result.instructionInitDataState.beforeEtlInitErrors.length) {
                    this.currentG6Node = result.instructionInitDataState.beforeEtlInitErrors[0];
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
                if (result.instructionInitDataState.beforeEtlInitFinishs && result.instructionInitDataState.beforeEtlInitFinishs.length) {
                    this.currentG6Node = result.instructionInitDataState.beforeEtlInitFinishs[0];
                    this.getEngineDetailData();
                    this.getEngineDetailTable();
                    return;
                }
            }
        });
    }

    // 获取引擎节点对应枚举
    private async getAllCodeEnum() {
        return new Promise((resolve, reject) => {
            this.$axios({ method: 'get', url: '/devopsmr/node/allCodeEnum' }).then((res: any) => {
                let enums = [
                    { recordSource: '0', typeCode: 'CH', typeDes: '财汇数据加载' },
                    { recordSource: '0', typeCode: 'GZ', typeDes: '估值数据加载' },
                    { recordSource: '0', typeCode: 'HS', typeDes: 'O32数据加载' },
                ];
                this.allCodeEnum = [...enums, ...res];
                resolve('success');

                // 筛选出 展示的节点 用于导出下拉框
                let arr = [
                    '外部条目加载',
                    '初始化指令号与序列号,清除恒生指令',
                    '穿透数据清理',
                    '动态维度加载',
                    '监控屏初始化配置',
                    '监控屏同申报缓存加载',
                    '内存数据加载',
                    '基础数据加载',
                    '转换持仓穿透',
                    '转换指令穿透',
                    '指令数据加载',
                    '原始范围加载',
                    '条目增量同步',
                    '动态维度增量同步',
                    '条目初始化',
                ];

                this.exportStorage = res.filter(item => arr.includes(item.typeDes));
            });
        });
    }

    // 获取引擎所有节点概述
    private async getAllNodeResult(operateType?: string) {
        return new Promise((resolve, reject) => {
            this.$axios({ method: 'get', url: '/devopsmr/node/result/all', headers: { operateType: operateType } }).then((res: any) => {
                let pojo = {};
                for (let i = 0; i < res.length; i++) {
                    if (res[i].startTime) {
                        res[i].startTime = PrefixInteger(res[i].startTime, 9);
                    }
                    if (res[i].endTime) {
                        res[i].endTime = PrefixInteger(res[i].endTime, 9);
                    }
                    res[i].startTime =
                        res[i].startTime && res[i].startTime.toString().length > 6
                            ? timeFormat(res[i].startTime.toString().substring(0, 6))
                            : timeFormat(res[i].startTime);
                    res[i].endTime =
                        res[i].endTime && res[i].endTime.toString().length > 6
                            ? timeFormat(res[i].endTime.toString().substring(0, 6))
                            : timeFormat(res[i].endTime);
                    if (res[i].startTime) {
                        res[i].startInitTime = dateFormat(res[i].startDate) + ' ' + timeFormat(res[i].startTime);
                    }
                    if (res[i].endTime) {
                        res[i].stopInitTime = dateFormat(res[i].endDate) + ' ' + timeFormat(res[i].endTime);
                    }
                    res[i].elapsedTime = this.calcCostTime(res[i].startInitTime, res[i].stopInitTime);

                    const node = this.allCodeEnum.find(item => item.typeCode === res[i].nodeCode);
                    if (node) {
                        pojo[node.typeDes] = res[i];
                    }
                }
                this.allNodeTips = pojo;

                resolve('success');
            });
        });
    }

    // 获取引擎节点状态
    private getEngineDetailData(operateType?: string): void {
        // debugger;
        console.log(this.currentG6Node, '------currentG6Node-----');
        if (this.currentG6Node === '引擎运行中') {
            this.getEngineStatusHistory(operateType);
            return;
        }
        // const currentG6Node = ['财汇数据加载', 'O32数据加载', '估值数据加载'].includes(this.currentG6Node) ? '外部数据加载' : this.currentG6Node;
        const node = this.allCodeEnum.find(item => item.typeDes === this.currentG6Node);
        this.$axios({
            method: 'get',
            url: '/devopsmr/node/result/' + node.recordSource + '/' + node.typeCode,
            headers: { operateType: operateType },
        }).then((res: any) => {
            res.percentComplete = res?.percentComplete * 100 || 0;
            if (res.startTime) {
                res.startTime = PrefixInteger(res.startTime, 9);
            }
            if (res.endTime) {
                res.endTime = PrefixInteger(res.endTime, 9);
            }

            res.startTime =
                res.startTime && res.startTime.toString().length > 6
                    ? timeFormat(res.startTime.toString().substring(0, 6))
                    : timeFormat(res.startTime);
            res.endTime =
                res.endTime && res.endTime.toString().length > 6 ? timeFormat(res.endTime.toString().substring(0, 6)) : timeFormat(res.endTime);
            if (res.startTime) {
                res.startInitTime = dateFormat(res.startDate) + ' ' + timeFormat(res.startTime);
            }
            if (res.endTime) {
                res.stopInitTime = dateFormat(res.endDate) + ' ' + timeFormat(res.endTime);
            }
            this.currentDetailMsg = res;
            this.currentDetailMsg.elapsedTime = this.calcCostTime(res.startInitTime, res.stopInitTime, this.elapsedTimer2, '2');
        });
    }

    private getEngineStatusHistory(operateType?: string): void {
        if (this.endTime && this.calculateEngineStateType == 'INITIALIZED') {
            const startTime = XEUtils.toDateString(new Date(), 'yyyy-MM-dd') + ' ' + this.endTime;
            const nowTime = XEUtils.toDateString(new Date(), 'yyyy-MM-dd HH:mm:ss');
            this.durationTime = this.calcCostTime(startTime, nowTime, this.elapsedTimer3, '3');
        } else {
            this.durationTime = '--';
        }
        this.$axios({
            method: 'post',
            url: '/devopsmr/engine/status/history',
            data: { ...this.searchParams2, paging: this.paging, sort: this.sortParam2 },
            headers: { operateType: operateType },
        }).then((res: any) => {
            this.tableDetailData2 = res.list;
        });
    }

    // 获取引擎节点表格
    private getEngineDetailTable(operateType?: string): void {
        const node = this.allCodeEnum.find(item => item.typeDes === this.currentG6Node);
        this.$axios({
            method: 'post',
            url: '/devopsmr/node/result/detail',
            data: { nodeCode: node.typeCode, recordSource: node.recordSource, ...this.searchParams, paging: this.paging, sort: this.sortParam },
            headers: { operateType: operateType },
        }).then((res: any) => {
            this.tableDetailData = res.list;

            // this.tableKey++;
            // this.changeTable();
        });
    }

    private async handleRefresh() {
        await this.getEngineData();
        await this.getAllNodeResult();
    }

    // 耗时计算
    private calcCostTime(startTime: string, endTime: string, timer?: any, type?: string) {
        if (type === '1') {
            clearInterval(this.elapsedTimer);
            this.elapsedTimer = null;
        }
        if (type === '2') {
            clearInterval(this.elapsedTimer2);
            this.elapsedTimer2 = null;
        }
        if (type === '3') {
            clearInterval(this.elapsedTimer3);
            this.elapsedTimer3 = null;
        }

        if (!startTime && !endTime) {
            return 0;
        }
        if (startTime && !endTime) {
            if (type === '1') {
                this.elapsedTimer = setInterval(() => {
                    this.elapsedTime += 1;
                }, 1000);
            }
            if (type === '2') {
                this.elapsedTimer2 = setInterval(() => {
                    this.currentDetailMsg.elapsedTime += 1;
                }, 1000);
            }
            return Number(((new Date().getTime() - new Date(startTime).getTime()) / 1000).toFixed(0));
        }

        if (type === '3') {
            this.elapsedTimer3 = setInterval(() => {
                this.durationTime += 1;
            }, 1000);
        }
        return Number(((new Date(endTime).getTime() - new Date(startTime).getTime()) / 1000).toFixed(0));
    }

    get getTimehms() {
        if (!this.durationTime || this.durationTime === '--' || !this.endTime) {
            return '--';
        }
        // 转换为式分秒
        let h: any = parseInt(((this.durationTime / 60 / 60) % 24).toString());
        h = h < 10 ? '0' + h : h;
        let m: any = parseInt(((this.durationTime / 60) % 60).toString());
        m = m < 10 ? '0' + m : m;
        let s: any = parseInt((this.durationTime % 60).toString());
        s = s < 10 ? '0' + s : s;

        return `${h}时${m}分${s}秒`;
    }

    // 时间格式化处理
    dealTime(time) {
        if (!time) {
            return '0 秒';
        }
        let diffTimeStr = '';
        // 转换为时分秒
        let h: any = parseInt(((time / 60 / 60) % 24).toString());
        let m: any = parseInt(((time / 60) % 60).toString());
        let s: any = parseInt((time % 60).toString());
        if (h) {
            // h = h < 10 ? '0' + h : h;
            diffTimeStr = `${h} 时 ${m} 分 ${s} 秒`;
        } else if (m) {
            // m = m < 10 ? '0' + m : m;
            diffTimeStr = `${m} 分 ${s} 秒`;
        } else if (s) {
            // s = s < 10 ? '0' + s : s;
            diffTimeStr = `${s} 秒`;
        } else {
            diffTimeStr = '0 秒';
        }
        return diffTimeStr;
    }

    private handleSort(val): void {
        const { order, property } = val;
        this.sortParam = this.handleSortField(order, property);
        this.getEngineDetailTable();
    }

    private handleFilter({ field, values, datas }): void {
        if (field === 'tableName' || field === 'logInfo') {
            this.searchParams[field] = datas.join('');
        } else if (field === 'resultType') {
            this.searchParams[field + 's'] = values;
        } else {
            this.searchParams[field] = values;
        }
        this.paging.currentPage = 1;
        this.getEngineDetailTable();
    }

    private handleSort2(val): void {
        const { order, property } = val;
        this.sortParam2 = this.handleSortField2(order, property);
        this.getEngineStatusHistory();
    }

    private handleFilter2({ field, values, datas }): void {
        if (field === 'newStatus' || field === 'oldStatus') {
            this.searchParams2[field + 'es'] = values;
        }
        this.paging.currentPage = 1;
        this.getEngineStatusHistory();
    }

    // 获取排序字段
    handleSortField(name: string, order: string): string {
        let value = '';
        if (name) {
            value = this.sortEnum[order] + ' ' + name;
        }
        return value;
    }

    // 获取排序字段
    handleSortField2(name: string, order: string): string {
        let value = '';
        if (name) {
            value = this.sortEnum2[order] + ' ' + name;
        }
        return value;
    }

    // 表格列筛选数据
    filterHandler({ option, row, column }) {
        const property = column['property'];
        return row[property].includes(option.data);
    }

    changeTable() {
        this.$nextTick(() => {
            this.iconDom = document.querySelectorAll('.vxe-icon--funnel');
            for (let i = 0; i < this.iconDom.length; i++) {
                if (this.changeIconCols.includes(i)) {
                    this.iconDom[i].className = 'vxe-filter--btn el-icon-search';
                }
            }
        });
    }

    /**
     * 转换数据格式 针对为undinefund的情况
     */
    changeDataFormat(data) {
        let orgData = JSON.parse(JSON.stringify(data));
        if (!data) {
            orgData = {};
        }
        if (!orgData.calculateEngineStateType) {
            orgData.calculateEngineStateType = 'UNINITIALIZED';
        }
        if (!orgData.instructionInitDataState) {
            orgData.instructionInitDataState = {};
        }

        for (let value of [
            'beforeEtlInits',
            'beforeEtlInitFinishs',
            'togetherEtlInits',
            'togetherEtlInitFinishs',
            'afterEtlInits',
            'afterEtlInitFinishs',
        ]) {
            if (!orgData.instructionInitDataState[value]) {
                orgData.instructionInitDataState[value] = [];
            }
        }
        return orgData;
    }

    private getResultTypeColor(val: string): string {
        let obj = {
            '0': 'green',
            '1': 'red',
            '2': 'blue',
        };
        return obj[val];
    }

    /**
     * 判断节点类型
     */
    judgeNodeType(orgData, nodeId, isdynamic) {
        if (orgData.engineStatus === 'UNINITIALIZED') {
            return INFO_NODE;
        }
        // debugger;
        // ETL之前是否为跳过状态
        let skipBeforEtl =
            orgData.instructionInitDataState.jumpOverETL === null || orgData.instructionInitDataState.jumpOverETL === undefined
                ? false
                : orgData.instructionInitDataState.jumpOverETL;
        // etl之前
        let tatalBefore = orgData.instructionInitDataState.beforeEtlInits;
        let beforEtl = orgData.instructionInitDataState.beforeEtlInitFinishs;
        let errorBeforEtl = orgData.instructionInitDataState.beforeEtlInitErrors;
        // etl之中
        let tatalTogether = orgData.instructionInitDataState.togetherEtlInits;
        let togetherEtl = orgData.instructionInitDataState.togetherEtlInitFinishs;
        let errorTogetherEtl = orgData.instructionInitDataState.togetherEtlInitErrors;
        // etl之后
        let tatalAfter = orgData.instructionInitDataState.afterEtlInits;
        let afterEtl = orgData.instructionInitDataState.afterEtlInitFinishs;
        let errorAfterEtl = orgData.instructionInitDataState.afterEtlInitErrors;
        // etl状态
        let etlState = orgData.instructionInitDataState.instrctionInitDataStateType;
        // 初始化总状态
        let entryState = (orgData.instructionEntryInitState || {}).entryInitStateType;
        if (orgData.calculateEngineStateType === 'INITIALIZED') {
            let split = (nodeId || '').split('-') || '';
            if (isdynamic && split[0] === 'before' && skipBeforEtl) {
                return SKIP_NODE;
            } else {
                return SUCCESS_EDGE;
            }
        }
        if (isdynamic) {
            let split = nodeId.split('-');
            if (split[0] === 'before') {
                if (beforEtl.includes(tatalBefore[Number(split[1]) - 1])) {
                    if (skipBeforEtl) {
                        return SKIP_NODE;
                    } else {
                        return SUCCESS_NODE;
                    }
                } else if (errorBeforEtl.includes(tatalBefore[Number(split[1]) - 1])) {
                    return ERROR_NODE;
                } else {
                    return SYNC_NODE;
                }
            } else if (split[0] === 'together') {
                if (etlState === 'BEFOR_ETL') {
                    return INFO_NODE;
                } else if (togetherEtl.includes(tatalTogether[Number(split[1]) - 1])) {
                    return SUCCESS_NODE;
                } else if (tatalBefore.length !== beforEtl.length) {
                    return INFO_NODE;
                } else if (errorTogetherEtl.includes(tatalTogether[Number(split[1]) - 1])) {
                    return ERROR_NODE;
                } else {
                    return SYNC_NODE;
                }
            } else if (split[0] === 'after') {
                if (['BEFOR_ETL', 'TOGETHER_ETL'].includes(etlState)) {
                    return INFO_NODE;
                } else if (afterEtl.includes(tatalAfter[Number(split[1]) - 1])) {
                    return SUCCESS_NODE;
                } else if (tatalTogether.length !== togetherEtl.length) {
                    return INFO_NODE;
                } else if (errorAfterEtl.includes(tatalAfter[Number(split[1]) - 1])) {
                    return ERROR_NODE;
                } else {
                    return SYNC_NODE;
                }
            }
        } else {
            if (nodeId === 'start') {
                return SUCCESS_NODE;
            } else if (nodeId === 'start-after') {
                return SUCCESS_NODE;
            } else if (nodeId === 'before-end') {
                if (etlState === 'UNINIT' && tatalBefore.length === beforEtl.length) {
                    return SUCCESS_NODE;
                } else if (etlState === 'BEFOR_ETL') {
                    return INFO_NODE;
                } else if (etlState === 'TOGETHER_ETL') {
                    return SUCCESS_NODE;
                } else if (etlState === 'AFTER_ETL') {
                    return SUCCESS_NODE;
                } else if (etlState === 'INIT_FINISH') {
                    return SUCCESS_NODE;
                } else {
                    return INFO_NODE;
                }
            } else if (nodeId === 'together-end') {
                if (etlState === 'UNINIT' && tatalTogether.length === togetherEtl.length) {
                    return SUCCESS_NODE;
                } else if (etlState === 'BEFOR_ETL') {
                    return INFO_NODE;
                } else if (etlState === 'TOGETHER_ETL') {
                    return INFO_NODE;
                } else if (etlState === 'AFTER_ETL') {
                    return SUCCESS_NODE;
                } else if (etlState === 'INIT_FINISH') {
                    return SUCCESS_NODE;
                } else {
                    return INFO_NODE;
                }
            } else if (nodeId === 'after-end') {
                if (etlState === 'UNINIT') {
                    return INFO_NODE;
                } else if (etlState === 'BEFOR_ETL') {
                    return INFO_NODE;
                } else if (etlState === 'TOGETHER_ETL') {
                    return INFO_NODE;
                } else if (etlState === 'AFTER_ETL') {
                    return INFO_NODE;
                } else if (etlState === 'INIT_FINISH') {
                    return SUCCESS_NODE;
                } else {
                    return INFO_NODE;
                }
            } else if (nodeId === 'entry') {
                if (entryState === 'UNINITIALIZED') {
                    return INFO_NODE;
                } else if (entryState === 'INIT_ENTRY' || orgData.calculateEngineStateType === 'INIT_ENTRY') {
                    return SYNC_NODE;
                } else if (entryState === 'INITIALIZED') {
                    return SUCCESS_NODE;
                } else {
                    return INFO_NODE;
                }
            } else if (nodeId === 'end') {
                return INFO_NODE;
            } else {
                return INFO_NODE;
            }
        }
        return INFO_NODE;
    }

    /**
     * 处理消息
     */
    handleMessage(data) {
        this.renderG6.clear();
        let orgData = JSON.parse(JSON.stringify(data));
        orgData = this.changeDataFormat(orgData);
        let x = 20;
        let nodes = [];
        let edges = [];
        let lastNodeId = 'start-after';
        nodes.push({
            id: 'start',
            x: x,
            y: 120,
            label: '开始',
            ...this.judgeNodeType(orgData, 'start', false),
            labelCfg: {
                position: 'bottom',
            },
        });
        x += 150;
        nodes.push({
            id: 'start-after',
            x: x,
            y: 120,
            ...this.judgeNodeType(orgData, 'start-after', false),
        });
        edges.push({
            source: 'start',
            target: 'start-after',
            style: {
                stroke: '#1890ff',
            },
            ...this.judgeEdgeType(orgData, 'start', 'start-after', false),
        });

        // etl之前
        let beforEtl = orgData.instructionInitDataState.beforeEtlInits;
        if (beforEtl.length !== 0) {
            x += 145;
        }
        if (beforEtl.length === 1) {
            nodes.push({
                id: 'before-1',
                x: x,
                y: 120,
                label: beforEtl[0],
                labelCfg: {
                    position: 'bottom',
                },
                initialize: this.allNodeTips[beforEtl[0]],
                ...this.judgeNodeType(orgData, 'before-1', true),
            });
            edges.push({
                source: lastNodeId,
                target: 'before-1',
                style: {
                    stroke: '#1890ff',
                },
                ...this.judgeEdgeType(orgData, lastNodeId, 'before-1', false),
            });
            edges.push({
                source: 'before-1',
                target: 'before-end',
                style: {
                    stroke: '#1890ff',
                },
                ...this.judgeEdgeType(orgData, 'before-1', 'before-end', true),
            });
        } else if (beforEtl.length > 1) {
            let interval = 200 / (beforEtl.length - 1);
            for (let i = 0; i < beforEtl.length; i++) {
                nodes.push({
                    id: 'before-' + (i + 1),
                    x: x,
                    y: 20 + i * interval,
                    label: beforEtl[i],
                    labelCfg: {
                        position: 'bottom',
                    },
                    initialize: this.allNodeTips[beforEtl[i]],
                    ...this.judgeNodeType(orgData, 'before-' + (i + 1), true),
                });
                edges.push({
                    source: lastNodeId,
                    target: 'before-' + (i + 1),
                    style: {
                        stroke: '#1890ff',
                    },
                    ...this.judgeEdgeType(orgData, lastNodeId, 'before-' + (i + 1), false),
                });
                edges.push({
                    source: 'before-' + (i + 1),
                    target: 'before-end',
                    style: {
                        stroke: '#1890ff',
                    },
                    ...this.judgeEdgeType(orgData, 'before-' + (i + 1), 'before-end', true),
                });
            }
        }
        if (beforEtl.length !== 0) {
            x += 145;
            lastNodeId = 'before-end';
            nodes.push({
                id: 'before-end',
                x: x,
                y: 120,
                ...this.judgeNodeType(orgData, 'before-end', false),
            });
        }
        // etl之中
        let togetherEtl = orgData.instructionInitDataState.togetherEtlInits;
        if (togetherEtl.length !== 0) {
            x += 145;
        }
        if (togetherEtl.length === 1) {
            nodes.push({
                id: 'together-1',
                x: x,
                y: 120,
                label: togetherEtl[0],
                labelCfg: {
                    position: 'bottom',
                },
                initialize: this.allNodeTips[togetherEtl[0]],
                ...this.judgeNodeType(orgData, 'together-1', true),
            });
            edges.push({
                source: lastNodeId,
                target: 'together-1',
                style: {
                    stroke: '#1890ff',
                },
                ...this.judgeEdgeType(orgData, lastNodeId, 'together-1', false),
            });
            edges.push({
                source: 'together-1',
                target: 'together-end',
                style: {
                    stroke: '#1890ff',
                },
                ...this.judgeEdgeType(orgData, 'together-1', 'together-end', true),
            });
        } else if (togetherEtl.length > 1) {
            let interval = 200 / (togetherEtl.length - 1);
            for (let i = 0; i < togetherEtl.length; i++) {
                nodes.push({
                    id: 'together-' + (i + 1),
                    x: x,
                    y: 20 + i * interval,
                    label: togetherEtl[i],
                    initialize: this.allNodeTips[togetherEtl[i]],
                    ...this.judgeNodeType(orgData, 'together-' + (i + 1), true),
                    labelCfg: {
                        position: 'bottom',
                    },
                });
                edges.push({
                    source: lastNodeId,
                    target: 'together-' + (i + 1),
                    style: {
                        stroke: '#1890ff',
                    },
                    ...this.judgeEdgeType(orgData, lastNodeId, 'together-' + (i + 1), false),
                });
                edges.push({
                    source: 'together-' + (i + 1),
                    target: 'together-end',
                    style: {
                        stroke: '#1890ff',
                    },
                    ...this.judgeEdgeType(orgData, 'together-' + (i + 1), 'together-end', true),
                });
            }
        }
        if (togetherEtl.length !== 0) {
            x += 145;
            lastNodeId = 'together-end';
            nodes.push({
                id: 'together-end',
                x: x,
                y: 120,
                ...this.judgeNodeType(orgData, 'together-end', false),
            });
        }
        // etl之后
        let afterEtl = orgData.instructionInitDataState.afterEtlInits;
        if (afterEtl.length !== 0) {
            x += 145;
        }
        if (afterEtl.length === 1) {
            nodes.push({
                id: 'after-1',
                x: x,
                y: 120,
                label: afterEtl[0],
                initialize: this.allNodeTips[afterEtl[0]],
                labelCfg: {
                    position: 'bottom',
                },
            });
            edges.push({
                source: lastNodeId,
                target: 'after-1',
                style: {
                    stroke: '#1890ff',
                },
                ...this.judgeEdgeType(orgData, lastNodeId, 'after-1', false),
            });
            edges.push({
                source: 'after-1',
                target: 'after-end',
                style: {
                    stroke: '#1890ff',
                },
                ...this.judgeEdgeType(orgData, 'after-1', 'after-end', true),
            });
        } else if (afterEtl.length > 1) {
            let interval = 200 / (afterEtl.length - 1);
            for (let i = 0; i < afterEtl.length; i++) {
                nodes.push({
                    id: 'after-' + (i + 1),
                    x: x,
                    y: 20 + i * interval,
                    label: afterEtl[i],
                    ...this.judgeNodeType(orgData, 'after-' + (i + 1), true),
                    initialize: this.allNodeTips[afterEtl[i]],
                    labelCfg: {
                        position: 'bottom',
                    },
                });
                edges.push({
                    source: lastNodeId,
                    target: 'after-' + (i + 1),
                    style: {
                        stroke: '#1890ff',
                    },
                    ...this.judgeEdgeType(orgData, lastNodeId, 'after-' + (i + 1), false),
                });
                edges.push({
                    source: 'after-' + (i + 1),
                    target: 'after-end',
                    style: {
                        stroke: '#1890ff',
                    },
                    ...this.judgeEdgeType(orgData, 'after-' + (i + 1), 'after-end', true),
                });
            }
        }
        if (afterEtl.length !== 0) {
            x += 145;
            lastNodeId = 'after-end';
            nodes.push({
                id: 'after-end',
                x: x,
                y: 120,
                ...this.judgeNodeType(orgData, 'after-end', false),
            });
        }
        edges.push({ source: lastNodeId, target: 'entry', ...this.judgeEdgeType(orgData, lastNodeId, 'entry', false) });
        x += 145;
        lastNodeId = 'entry';
        nodes.push({
            id: 'entry',
            x: x,
            y: 120,
            label: '条目初始化',
            initialize: this.allNodeTips['条目初始化'],
            ...this.judgeNodeType(orgData, 'entry', false),
            labelCfg: {
                position: 'bottom',
            },
        });
        x += 145;
        nodes.push({
            id: 'end',
            x: x,
            y: 120,
            label: '引擎运行中',
            initialize: this.allNodeTips['引擎运行中'],
            ...this.judgeNodeType(orgData, 'end', false),
            labelCfg: {
                position: 'bottom',
            },
        });
        edges.push({ source: lastNodeId, target: 'end', ...this.judgeEdgeType(orgData, lastNodeId, 'end', false) });
        // 读取数据
        this.renderG6.data({ nodes: nodes, edges: edges });

        // 解析nodes 渲染简易步骤条
        this.renderSteps(nodes);

        // 渲染图
        this.renderG6.render();
    }

    private renderSteps(nodes: any): void {
        let stepStatus = this.stepStatus;
        // 开始
        let start = nodes.filter(item => item.label === '开始');
        // 外部数据加载
        let outside = nodes.filter(item =>
            ['外部条目加载', '外部数据加载', '初始化指令号与序列号,清除恒生指令', '穿透数据清理', '动态维度加载'].includes(item.label)
        );
        // 内部数据加载
        let inside = nodes.filter(item =>
            ['监控屏同申报缓存加载', '监控屏初始化配置', '内存数据加载', '基础数据加载', '转换持仓穿透'].includes(item.label)
        );
        // 数据转换加载
        let dataConversion = nodes.filter(item =>
            ['转换指令穿透', '动态维度增量同步', '指令数据加载', '原始范围加载', '条目增量同步'].includes(item.label)
        );
        // 条目初始化
        let entry = nodes.filter(item => item.label === '条目初始化');
        // 引擎运行中
        let engine = nodes.filter(item => item.label === '引擎运行中');

        stepStatus['start'] = start[0] ? start[0].state : 'wait';

        if (this.jumpOverETL && this.calculateEngineStateType) {
            stepStatus['outside'] = 'finish';
        } else {
            if (outside.every(item => item.state === 'finish')) {
                stepStatus['outside'] = 'finish';
            } else if (outside.some(item => item.state === 'error')) {
                stepStatus['outside'] = 'error';
            } else if (outside.some(item => item.state === 'loading')) {
                stepStatus['outside'] = 'loading';
            } else {
                stepStatus['outside'] = 'wait';
            }
        }

        if (inside.every(item => item.state === 'finish')) {
            stepStatus['inside'] = 'finish';
        } else if (inside.some(item => item.state === 'error')) {
            stepStatus['inside'] = 'error';
        } else if (inside.some(item => item.state === 'loading')) {
            stepStatus['inside'] = 'loading';
        } else {
            stepStatus['inside'] = 'wait';
        }

        if (dataConversion.every(item => item.state === 'finish')) {
            stepStatus['dataConversion'] = 'finish';
        } else if (dataConversion.some(item => item.state === 'error')) {
            stepStatus['dataConversion'] = 'error';
        } else if (dataConversion.some(item => item.state === 'loading')) {
            stepStatus['dataConversion'] = 'loading';
        } else {
            stepStatus['dataConversion'] = 'wait';
        }

        stepStatus['entry'] = entry[0] ? entry[0].state : 'wait';
        stepStatus['engine'] = engine[0] && engine[0].state === 'finish' ? 'finallySuccess' : 'finallyWait';

        this.stepStatus = stepStatus;
    }

    /**
     * 判断连线类型
     */
    judgeEdgeType(orgData, sourceId, targetId, isdynamic) {
        if (orgData.engineStatus === 'UNINITIALIZED') {
            return INFO_EDGE;
        }
        if (orgData.calculateEngineStateType === 'INITIALIZED') {
            return SUCCESS_EDGE;
        }
        // etl之前
        let tatalBefore = orgData.instructionInitDataState.beforeEtlInits;
        let beforEtl = orgData.instructionInitDataState.beforeEtlInitFinishs;
        let errorBeforEtl = orgData.instructionInitDataState.beforeEtlInitErrors;
        // etl之中
        let tatalTogether = orgData.instructionInitDataState.togetherEtlInits;
        let togetherEtl = orgData.instructionInitDataState.togetherEtlInitFinishs;
        let errorTogetherEtl = orgData.instructionInitDataState.togetherEtlInitErrors;
        // etl之后
        let tatalAfter = orgData.instructionInitDataState.afterEtlInits;
        let afterEtl = orgData.instructionInitDataState.afterEtlInitFinishs;
        let errorAfterEtl = orgData.instructionInitDataState.afterEtlInitErrors;
        // etl状态
        let etlState = orgData.instructionInitDataState.instrctionInitDataStateType;
        // 条目状态
        let entryState = (orgData.instructionEntryInitState || {}).entryInitStateType;
        if (isdynamic) {
            let split = sourceId.split('-');
            if (split[0] === 'before') {
                if (beforEtl.includes(tatalBefore[Number(split[1]) - 1])) {
                    return SUCCESS_EDGE;
                } else if (errorBeforEtl.includes(tatalBefore[Number(split[1]) - 1])) {
                    return ERROR_EDGE;
                } else {
                    return SYNC_EDGE;
                }
            } else if (split[0] === 'together') {
                if (etlState === 'BEFOR_ETL') {
                    return INFO_EDGE;
                } else if (togetherEtl.includes(tatalTogether[Number(split[1]) - 1])) {
                    return SUCCESS_EDGE;
                } else if (tatalBefore.length !== beforEtl.length) {
                    return INFO_EDGE;
                } else if (errorTogetherEtl.includes(tatalTogether[Number(split[1]) - 1])) {
                    return ERROR_EDGE;
                } else {
                    return SYNC_EDGE;
                }
            } else if (split[0] === 'after') {
                if (['BEFOR_ETL', 'TOGETHER_ETL'].includes(etlState)) {
                    return INFO_EDGE;
                } else if (afterEtl.includes(tatalAfter[Number(split[1]) - 1])) {
                    return SUCCESS_EDGE;
                } else if (tatalTogether.length !== togetherEtl.length) {
                    return INFO_EDGE;
                } else if (errorAfterEtl.includes(tatalAfter[Number(split[1]) - 1])) {
                    return ERROR_EDGE;
                } else {
                    return SYNC_EDGE;
                }
            }
            return INFO_EDGE;
        } else {
            if (sourceId === 'start') {
                return SUCCESS_EDGE;
            } else if (sourceId === 'start-after') {
                return SUCCESS_EDGE;
            } else if (sourceId === 'before-end') {
                if (etlState === 'UNINIT' && tatalBefore.length === beforEtl.length) {
                    return SUCCESS_EDGE;
                } else if (etlState === 'BEFOR_ETL') {
                    return INFO_EDGE;
                } else if (etlState === 'TOGETHER_ETL') {
                    return SUCCESS_EDGE;
                } else if (etlState === 'AFTER_ETL') {
                    return SUCCESS_EDGE;
                } else if (etlState === 'INIT_FINISH') {
                    if (targetId === 'entry') {
                        if (orgData.calculateEngineStateType === 'INIT_DATA') {
                            return SYNC_EDGE;
                        } else {
                            return SUCCESS_EDGE;
                        }
                    } else {
                        return SUCCESS_EDGE;
                    }
                } else {
                    return INFO_EDGE;
                }
            } else if (sourceId === 'together-end') {
                if (etlState === 'UNINIT' && tatalTogether.length === togetherEtl.length) {
                    return SUCCESS_EDGE;
                } else if (etlState === 'BEFOR_ETL') {
                    return INFO_EDGE;
                } else if (etlState === 'TOGETHER_ETL') {
                    return INFO_EDGE;
                } else if (etlState === 'AFTER_ETL') {
                    return SUCCESS_EDGE;
                } else if (etlState === 'INIT_FINISH') {
                    if (targetId === 'entry') {
                        if (orgData.calculateEngineStateType === 'INIT_DATA') {
                            return SYNC_EDGE;
                        } else {
                            return SUCCESS_EDGE;
                        }
                    } else {
                        return SUCCESS_EDGE;
                    }
                } else {
                    return INFO_EDGE;
                }
            } else if (sourceId === 'after-end') {
                if (etlState === 'UNINIT') {
                    return INFO_EDGE;
                } else if (etlState === 'BEFOR_ETL') {
                    return INFO_EDGE;
                } else if (etlState === 'TOGETHER_ETL') {
                    return INFO_EDGE;
                } else if (etlState === 'AFTER_ETL') {
                    return INFO_EDGE;
                } else if (etlState === 'INIT_FINISH') {
                    if (targetId === 'entry') {
                        if (orgData.calculateEngineStateType === 'INIT_DATA') {
                            return SYNC_EDGE;
                        } else {
                            return SUCCESS_EDGE;
                        }
                    } else {
                        return SUCCESS_EDGE;
                    }
                } else {
                    return INFO_EDGE;
                }
            } else if (sourceId === 'entry') {
                if (entryState === 'UNINITIALIZED') {
                    return INFO_EDGE;
                } else if (entryState === 'INIT_ENTRY' || orgData.calculateEngineStateType === 'INIT_ENTRY') {
                    return SYNC_EDGE;
                } else if (entryState === 'INITIALIZED') {
                    return SUCCESS_EDGE;
                } else {
                    return INFO_EDGE;
                }
            } else {
                return INFO_EDGE;
            }
        }
    }

    private handleExport(): void {
        const node = this.allCodeEnum.find(item => item.typeDes === this.currentG6Node);
        this.exportG6Node = node?.typeCode || (this.currentG6Node === '引擎运行中' ? '当日引擎运行状态更新记录' : this.currentG6Node);
        this.exportVisible = true;
    }

    private exportList(name?: string) {
        this.exportLoading = true;
        let nodeCode = this.exportG6Node;
        if (name === '当日引擎运行状态更新记录') {
            nodeCode = ''; // 导出所有
        }
        const node = this.allCodeEnum.find(item => item.typeCode === nodeCode) || { recordSource: '1' };
        if (nodeCode === '当日引擎运行状态更新记录') {
            downLoadFile({
                url: '/devopsmr/engine/status/history/export',
                method: 'post',
                data: { nodeCode, ...this.searchParams2, sort: this.sortParam2, paging: this.paging },
            })
                .then((res: any) => {
                    this.exportVisible = false;
                    this.exportLoading = false;
                })
                .catch(() => {
                    this.exportVisible = false;
                    this.exportLoading = false;
                });
        } else {
            downLoadFile({
                url: '/devopsmr/node/result/detail/export',
                method: 'post',
                data: { nodeCode, recordSource: node.recordSource, ...this.searchParams, sort: this.sortParam },
            })
                .then((res: any) => {
                    this.exportVisible = false;
                    this.exportLoading = false;
                })
                .catch(() => {
                    this.exportVisible = false;
                    this.exportLoading = false;
                });
        }
    }

    private getStyle(val: string, value: string): any {
        let color = '';
        if (['oldStatus', 'newStatus', 'resultType'].includes(val)) {
            color = value == '0' ? 'green' : value == '1' ? 'red' : '';
        }
        if (['resultType'].includes(val)) {
            color = value == '1' ? 'red' : value == '0' ? 'green' : '';
        }
        return { color: color };
    }
}
</script>

<style lang="scss" scoped>
@import '../../../assets/style/serve-execution-monitor.scss';
@import '@/pages/report/styles/common';
.g6-wrap {
    height: 100%;
}

/deep/ .el-step__title {
    font-size: 14px;
    font-weight: 600;
    color: rgba(0, 0, 0, 0.65);
}

/deep/ .el-step__line-inner {
    border-width: 0.5px !important;
    width: 100% !important;
}

/deep/ .el-step__icon.is-icon {
    width: 30px;
}
/deep/ .el-step__main {
    position: absolute;
    top: -8px;
    left: 30px;
}
/deep/.el-step__line {
    height: 1px;
    top: 11px;
    left: 75px;
    right: 5px;
}
.el-steps--horizontal {
    position: absolute;
    left: 150px;
    width: 75%;
    z-index: 123;
    top: 2px;
    .el-step {
        &:nth-child(1) {
            /deep/.el-step__line {
                left: 80px !important;
            }
        }
        &:nth-child(2) {
            /deep/.el-step__line {
                left: 120px !important;
            }
        }
        &:nth-child(3) {
            /deep/.el-step__line {
                left: 120px !important;
            }
        }
        &:nth-child(4) {
            /deep/.el-step__line {
                left: 120px !important;
            }
        }
        &:nth-child(5) {
            /deep/.el-step__line {
                left: 110px !important;
            }
        }
    }
}

/deep/.el-step__title,
.is-wait {
    width: max-content;
}
/deep/ .el-step__title.is-error {
    color: red;
}

.my-input {
    margin: 10px;
    width: 150px;
}

.table-box /deep/ .el-progress-circle svg > path:nth-child(2) {
    stroke: rgb(135, 208, 104);
}

// /deep/ .vxe-table--body {
//     width: 100% !important;
// }
</style>
<style lang="scss">
.el-tooltip__popper {
    margin: 5px !important;
}

.monitor-tooltip {
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.3) !important;
    background-color: rgba(255, 255, 255, 0.8) !important;
    border-color: rgba(0, 0, 0, 0.1) !important;
    color: rgba(0, 0, 0, 0.65);
    border-width: 0px;
    padding: 5px 10px;
}

.monitor-tooltip .popper__arrow {
    display: none;
}
</style>
